!theme mono

skinparam classAttributeIconSize 0
skinparam classFontSize 12
skinparam classAttributeFontSize 11

title HealthSync 역설계 - Clean Architecture 기반 클래스 설계서

package "healthsync-root" {
    
    package "common" {
        class JwtConfig {
            +secretKey: String
            +accessTokenValidityInSeconds: long
            +refreshTokenValidityInSeconds: long
            +generateToken(userDetails: UserDetails): String
            +validateToken(token: String): boolean
            +extractUsername(token: String): String
        }
        
        class SecurityConfig {
            +jwtAuthenticationEntryPoint: JwtAuthenticationEntryPoint
            +jwtRequestFilter: JwtRequestFilter
            +passwordEncoder(): BCryptPasswordEncoder
            +authenticationManager(): AuthenticationManager
        }
        
        class GlobalExceptionHandler {
            +handleBusinessException(ex: BusinessException): ResponseEntity
            +handleValidationException(ex: ValidationException): ResponseEntity
            +handleAuthenticationException(ex: AuthenticationException): ResponseEntity
            +handleGenericException(ex: Exception): ResponseEntity
        }
        
        class ApiResponse<T> {
            +success: boolean
            +data: T
            +message: String
            +timestamp: LocalDateTime
            +of(data: T): ApiResponse<T>
            +error(message: String): ApiResponse<Void>
        }
        
        abstract class BaseEntity {
            +id: Long
            +createdAt: LocalDateTime
            +updatedAt: LocalDateTime
            +version: Long
        }
        
        class BusinessException {
            +errorCode: ErrorCode
            +message: String
            +BusinessException(errorCode: ErrorCode, message: String)
        }
        
        enum ErrorCode {
            USER_NOT_FOUND,
            INVALID_CREDENTIALS,
            HEALTH_DATA_NOT_FOUND,
            MISSION_NOT_FOUND,
            UNAUTHORIZED_ACCESS,
            VALIDATION_FAILED
        }
    }
    
    package "user-service" {
        class UserServiceApplication {
            +main(args: String[]): void
        }
        
        package "interface-adapters" {
            package "controllers" {
                class AuthController {
                    -authUseCase: AuthUseCase
                    -userUseCase: UserUseCase
                    +googleLogin(request: GoogleLoginRequest): ResponseEntity<LoginResponse>
                    +completeProfile(request: UserRegistrationRequest): ResponseEntity<UserRegistrationResponse>
                    +getProfile(): ResponseEntity<UserProfileResponse>
                }
                
                class UserController {
                    -userUseCase: UserUseCase
                    +getAllOccupations(): ResponseEntity<OccupationListResponse>
                    +getOccupationName(occupationCode: String): ResponseEntity<OccupationNameResponse>
                    +getOccupationCode(occupationName: String): ResponseEntity<OccupationCodeResponse>
                }
            }
            
            package "adapters" {
                class GoogleAuthAdapter {
                    -googleTokenVerifier: GoogleIdTokenVerifier
                    +verifyGoogleToken(accessToken: String, idToken: String): GoogleUserInfo
                    +extractUserInfo(idToken: GoogleIdToken): GoogleUserInfo
                }
                
                class JwtTokenAdapter {
                    -jwtConfig: JwtConfig
                    +generateTokens(user: User): TokenPair
                    +validateToken(token: String): boolean
                    +extractUserId(token: String): String
                }
                
                class EventPublisherAdapter {
                    -serviceBusTemplate: ServiceBusTemplate
                    +publishUserRegisteredEvent(user: User): void
                    +publishUserProfileUpdatedEvent(user: User): void
                }
            }
        }
        
        package "application-services" {
            class AuthUseCase {
                -authDomainService: AuthDomainService
                -userRepository: UserRepository
                -jwtTokenAdapter: JwtTokenAdapter
                -eventPublisher: EventPublisherAdapter
                +authenticateWithGoogle(request: GoogleLoginRequest): LoginResponse
                +refreshToken(refreshToken: String): TokenPair
            }
            
            class UserUseCase {
                -userDomainService: UserDomainService
                -userRepository: UserRepository
                -occupationRepository: OccupationRepository
                -eventPublisher: EventPublisherAdapter
                +completeUserProfile(request: UserRegistrationRequest): UserRegistrationResponse
                +getUserProfile(userId: String): UserProfileResponse
                +getAllOccupations(): OccupationListResponse
                +convertOccupationCodeToName(code: String): String
                +convertOccupationNameToCode(name: String): String
            }
        }
        
        package "domain" {
            package "model" {
                class User {
                    +memberSerialNumber: Long
                    +googleId: String
                    +name: String
                    +birthDate: LocalDate
                    +occupation: String
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +lastLoginAt: LocalDateTime
                    +calculateAge(): int
                    +isProfileComplete(): boolean
                    +updateProfile(name: String, birthDate: LocalDate, occupation: String): void
                }
                
                class OccupationType {
                    +occupationCode: String
                    +occupationName: String
                    +category: String
                    +isValidCode(code: String): boolean
                }
                
                class GoogleUserInfo {
                    +googleId: String
                    +email: String
                    +name: String
                    +picture: String
                    +isValid(): boolean
                }
            }
            
            package "services" {
                class AuthDomainService {
                    +validateGoogleTokens(accessToken: String, idToken: String): GoogleUserInfo
                    +createNewUser(googleUserInfo: GoogleUserInfo): User
                    +updateLastLogin(user: User): User
                }
                
                class UserDomainService {
                    +validateProfileData(profileData: UserRegistrationRequest): void
                    +updateUserProfile(user: User, profileData: UserRegistrationRequest): User
                    +calculateAge(birthDate: LocalDate): int
                }
            }
            
            package "repositories" {
                interface UserRepository {
                    +findByGoogleId(googleId: String): Optional<User>
                    +findById(id: Long): Optional<User>
                    +save(user: User): User
                    +updateLastLoginAt(id: Long): void
                    +existsByGoogleId(googleId: String): boolean
                }
                
                interface OccupationRepository {
                    +findAll(): List<OccupationType>
                    +findByOccupationCode(code: String): Optional<OccupationType>
                    +findByOccupationName(name: String): Optional<OccupationType>
                    +validateOccupationCode(code: String): boolean
                }
            }
        }
        
        package "infrastructure" {
            package "repositories" {
                class UserRepositoryImpl {
                    -entityManager: EntityManager
                    +findByGoogleId(googleId: String): Optional<User>
                    +findById(id: Long): Optional<User>
                    +save(user: User): User
                    +updateLastLoginAt(id: Long): void
                    +existsByGoogleId(googleId: String): boolean
                }
                
                class OccupationRepositoryImpl {
                    -entityManager: EntityManager
                    +findAll(): List<OccupationType>
                    +findByOccupationCode(code: String): Optional<OccupationType>
                    +findByOccupationName(name: String): Optional<OccupationType>
                    +validateOccupationCode(code: String): boolean
                }
            }
            
            package "entities" {
                class UserEntity {
                    +memberSerialNumber: Long
                    +googleId: String
                    +name: String
                    +birthDate: LocalDate
                    +occupation: String
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +lastLoginAt: LocalDateTime
                    +toDomain(): User
                    +fromDomain(user: User): UserEntity
                }
                
                class OccupationTypeEntity {
                    +occupationCode: String
                    +occupationName: String
                    +category: String
                    +toDomain(): OccupationType
                }
            }
        }
        
        package "dto" {
            class GoogleLoginRequest {
                +googleAccessToken: String
                +googleIdToken: String
            }
            
            class LoginResponse {
                +accessToken: String
                +refreshToken: String
                +userId: String
                +isNewUser: boolean
                +message: String
            }
            
            class UserRegistrationRequest {
                +name: String
                +birthDate: String
                +occupation: String
            }
            
            class UserRegistrationResponse {
                +userId: String
                +message: String
                +status: String
                +profileCompletedAt: String
            }
            
            class UserProfileResponse {
                +userId: String
                +name: String
                +age: int
                +occupation: String
                +registeredAt: String
                +lastLoginAt: String
            }
            
            class OccupationListResponse {
                +occupations: List<OccupationDto>
                +totalCount: int
            }
            
            class OccupationDto {
                +occupationCode: String
                +occupationName: String
                +category: String
            }
        }
    }
    
    package "health-service" {
        class HealthServiceApplication {
            +main(args: String[]): void
        }
        
        package "interface-adapters" {
            package "controllers" {
                class HealthController {
                    -checkupSyncUseCase: CheckupSyncUseCase
                    -checkupQueryUseCase: CheckupQueryUseCase
                    -fileUploadUseCase: FileUploadUseCase
                    +syncCheckupData(userId: String): ResponseEntity<HealthSyncResponse>
                    +getCheckupHistory(userId: String, limit: int): ResponseEntity<HealthHistoryResponse>
                    +uploadCheckupFile(request: CheckupFileRequest): ResponseEntity<FileUploadResponse>
                    +getNormalRanges(genderCode: int): ResponseEntity<NormalRangeResponse>
                }
            }
            
            package "adapters" {
                class UserServiceAdapter {
                    -userServiceClient: UserServiceClient
                    +getUserInfo(userId: String): UserInfo
                    +getUserBasicInfo(userId: String): UserBasicInfo
                }
                
                class BlobStorageAdapter {
                    -blobServiceClient: BlobServiceClient
                    +uploadFile(fileContent: String, fileName: String): String
                    +generateSasToken(containerName: String, fileName: String): String
                    +downloadFile(blobUrl: String): byte[]
                }
                
                class CacheAdapter {
                    -redisTemplate: RedisTemplate
                    +getCachedHistory(userId: String): HealthHistoryResponse
                    +cacheHistory(userId: String, response: HealthHistoryResponse): void
                    +getCachedNormalRanges(genderCode: int): List<NormalRange>
                    +cacheNormalRanges(genderCode: int, ranges: List<NormalRange>): void
                    +invalidateUserHealthCache(userId: String): void
                }
                
                class EventPublisherAdapter {
                    -serviceBusTemplate: ServiceBusTemplate
                    +publishHealthDataSyncedEvent(userId: String, syncResult: HealthSyncResult): void
                    +publishFileUploadedEvent(userId: String, fileInfo: FileInfo): void
                }
            }
        }
        
        package "application-services" {
            class CheckupSyncUseCase {
                -healthProfileDomainService: HealthProfileDomainService
                -checkupAnalysisDomainService: CheckupAnalysisDomainService
                -healthRepository: HealthRepository
                -healthCheckupRawRepository: HealthCheckupRawRepository
                -normalRangeRepository: NormalRangeRepository
                -userServiceAdapter: UserServiceAdapter
                -cacheAdapter: CacheAdapter
                -eventPublisher: EventPublisherAdapter
                +syncCheckupData(userId: String): HealthSyncResponse
                +processRawCheckupData(rawData: List<HealthCheckupRaw>, userInfo: UserInfo): HealthSyncResult
            }
            
            class CheckupQueryUseCase {
                -healthRepository: HealthRepository
                -normalRangeRepository: NormalRangeRepository
                -checkupAnalysisDomainService: CheckupAnalysisDomainService
                -cacheAdapter: CacheAdapter
                +getHealthCheckupHistory(userId: String, limit: int): HealthHistoryResponse
                +getNormalRangesByGender(genderCode: int): NormalRangeResponse
                +analyzeHealthTrend(checkupHistory: List<HealthCheckup>): TrendAnalysis
            }
            
            class FileUploadUseCase {
                -blobStorageAdapter: BlobStorageAdapter
                -healthRepository: HealthRepository
                -eventPublisher: EventPublisherAdapter
                +uploadCheckupFile(request: CheckupFileRequest): FileUploadResponse
                +validateFileFormat(fileType: String, fileContent: String): void
                +saveFileMetadata(fileInfo: FileInfo): HealthFile
            }
        }
        
        package "domain" {
            package "model" {
                class HealthCheckup {
                    +id: Long
                    +userId: String
                    +memberSerialNumber: Long
                    +rawId: Long
                    +referenceYear: int
                    +heightCm: double
                    +weightKg: double
                    +waistCm: double
                    +bmi: double
                    +visualAcuityLeft: double
                    +visualAcuityRight: double
                    +hearingAvg: double
                    +systolicBp: int
                    +diastolicBp: int
                    +fastingGlucose: int
                    +totalCholesterol: int
                    +triglyceride: int
                    +hdlCholesterol: int
                    +ldlCholesterol: int
                    +hemoglobin: double
                    +urineProtein: int
                    +serumCreatinine: double
                    +ast: int
                    +alt: int
                    +gammaGtp: int
                    +smokingStatus: int
                    +drinkingStatus: int
                    +riskLevel: String
                    +abnormalIndicators: String
                    +healthScore: int
                    +createdAt: LocalDateTime
                    +calculateBMI(): double
                    +determineRiskLevel(): String
                    +isNormalBMI(): boolean
                    +isNormalBloodPressure(): boolean
                }
                
                class HealthCheckupRaw {
                    +rawId: Long
                    +memberSerialNumber: Long
                    +referenceYear: int
                    +birthDate: LocalDate
                    +name: String
                    +regionCode: int
                    +genderCode: int
                    +age: int
                    +height: int
                    +weight: int
                    +waistCircumference: int
                    +visualAcuityLeft: double
                    +visualAcuityRight: double
                    +hearingLeft: int
                    +hearingRight: int
                    +systolicBp: int
                    +diastolicBp: int
                    +fastingGlucose: int
                    +totalCholesterol: int
                    +triglyceride: int
                    +hdlCholesterol: int
                    +ldlCholesterol: int
                    +hemoglobin: double
                    +urineProtein: int
                    +serumCreatinine: double
                    +ast: int
                    +alt: int
                    +gammaGtp: int
                    +smokingStatus: int
                    +drinkingStatus: int
                    +isValidData(): boolean
                    +convertToStandardUnits(): HealthCheckupRaw
                }
                
                class NormalRange {
                    +itemCode: String
                    +itemName: String
                    +genderCode: int
                    +normalMin: double
                    +normalMax: double
                    +cautionMin: double
                    +cautionMax: double
                    +dangerMin: double
                    +dangerMax: double
                    +unit: String
                    +description: String
                    +evaluateValue(value: double): RangeStatus
                    +isApplicableForGender(genderCode: int): boolean
                }
                
                enum RangeStatus {
                    NORMAL, CAUTION, DANGER, UNKNOWN
                }
                
                class HealthFile {
                    +fileId: String
                    +userId: String
                    +fileName: String
                    +fileType: String
                    +fileUrl: String
                    +fileSize: long
                    +uploadStatus: String
                    +uploadedAt: LocalDateTime
                    +isValidFileType(): boolean
                    +generateSasUrl(): String
                }
            }
            
            package "services" {
                class HealthProfileDomainService {
                    +validateHealthData(checkupData: HealthCheckupRaw): void
                    +transformRawToCheckup(rawData: HealthCheckupRaw, userInfo: UserInfo): HealthCheckup
                    +calculateHealthScore(checkup: HealthCheckup, normalRanges: List<NormalRange>): int
                    +determineOverallRiskLevel(indicatorResults: Map<String, RangeStatus>): String
                }
                
                class CheckupAnalysisDomainService {
                    +analyzeWithNormalRanges(checkup: HealthCheckup, normalRanges: List<NormalRange>): AnalysisResult
                    +compareWithNormalRange(value: double, range: NormalRange): RangeStatus
                    +identifyAbnormalIndicators(analysisResults: Map<String, RangeStatus>): List<String>
                    +calculateTrendAnalysis(checkupHistory: List<HealthCheckup>): TrendAnalysis
                    +generateHealthInsights(checkup: HealthCheckup): List<String>
                }
                
                class NormalRangeDomainService {
                    +validateNormalRangeData(range: NormalRange): void
                    +getRangesByGender(genderCode: int, allRanges: List<NormalRange>): List<NormalRange>
                    +parseRangeValue(rangeString: String): RangeValue
                    +formatRangeDisplay(range: NormalRange): String
                }
            }
            
            package "repositories" {
                interface HealthRepository {
                    +findByMemberSerialNumber(memberSerialNumber: Long): Optional<HealthCheckup>
                    +findCheckupHistoryWithDetails(userId: String, limit: int): List<HealthCheckup>
                    +saveOrUpdateHealthCheckup(entity: HealthCheckup): HealthCheckup
                    +findExistingCheckupRecords(userId: String): List<Integer>
                    +saveFileMetadata(fileMetadata: HealthFile): HealthFile
                    +findFilesByUserId(userId: String): List<HealthFile>
                }
                
                interface HealthCheckupRawRepository {
                    +findNhisCheckupDataByMemberSerial(memberSerialNumber: Long): List<HealthCheckupRaw>
                    +findTop5ByNameAndBirthDateOrderByReferenceYearDescCreatedAtDesc(name: String, birthDate: LocalDate): List<HealthCheckupRaw>
                    +findByMemberSerialNumberAndReferenceYear(memberSerialNumber: Long, year: int): Optional<HealthCheckupRaw>
                }
                
                interface NormalRangeRepository {
                    +getNormalRangesByGender(genderCode: int): List<NormalRange>
                    +findByItemCodeAndGender(itemCode: String, genderCode: int): Optional<NormalRange>
                    +findAllActiveRanges(): List<NormalRange>
                    +updateNormalRange(range: NormalRange): NormalRange
                }
            }
        }
        
        package "infrastructure" {
            package "repositories" {
                class HealthRepositoryImpl {
                    -entityManager: EntityManager
                    +findByMemberSerialNumber(memberSerialNumber: Long): Optional<HealthCheckup>
                    +findCheckupHistoryWithDetails(userId: String, limit: int): List<HealthCheckup>
                    +saveOrUpdateHealthCheckup(entity: HealthCheckup): HealthCheckup
                    +findExistingCheckupRecords(userId: String): List<Integer>
                    +saveFileMetadata(fileMetadata: HealthFile): HealthFile
                    +findFilesByUserId(userId: String): List<HealthFile>
                }
                
                class HealthCheckupRawRepositoryImpl {
                    -entityManager: EntityManager
                    +findNhisCheckupDataByMemberSerial(memberSerialNumber: Long): List<HealthCheckupRaw>
                    +findTop5ByNameAndBirthDateOrderByReferenceYearDescCreatedAtDesc(name: String, birthDate: LocalDate): List<HealthCheckupRaw>
                    +findByMemberSerialNumberAndReferenceYear(memberSerialNumber: Long, year: int): Optional<HealthCheckupRaw>
                }
                
                class NormalRangeRepositoryImpl {
                    -entityManager: EntityManager
                    +getNormalRangesByGender(genderCode: int): List<NormalRange>
                    +findByItemCodeAndGender(itemCode: String, genderCode: int): Optional<NormalRange>
                    +findAllActiveRanges(): List<NormalRange>
                    +updateNormalRange(range: NormalRange): NormalRange
                }
            }
            
            package "entities" {
                class HealthCheckupEntity {
                    +id: Long
                    +userId: String
                    +memberSerialNumber: Long
                    +rawId: Long
                    +referenceYear: int
                    +heightCm: double
                    +weightKg: double
                    +waistCm: double
                    +bmi: double
                    +visualAcuityLeft: double
                    +visualAcuityRight: double
                    +hearingAvg: double
                    +systolicBp: int
                    +diastolicBp: int
                    +fastingGlucose: int
                    +totalCholesterol: int
                    +triglyceride: int
                    +hdlCholesterol: int
                    +ldlCholesterol: int
                    +hemoglobin: double
                    +urineProtein: int
                    +serumCreatinine: double
                    +ast: int
                    +alt: int
                    +gammaGtp: int
                    +smokingStatus: int
                    +drinkingStatus: int
                    +riskLevel: String
                    +abnormalIndicators: String
                    +healthScore: int
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +toDomain(): HealthCheckup
                    +fromDomain(checkup: HealthCheckup): HealthCheckupEntity
                }
                
                class HealthCheckupRawEntity {
                    +rawId: Long
                    +memberSerialNumber: Long
                    +referenceYear: int
                    +birthDate: LocalDate
                    +name: String
                    +regionCode: int
                    +genderCode: int
                    +age: int
                    +height: int
                    +weight: int
                    +waistCircumference: int
                    +visualAcuityLeft: double
                    +visualAcuityRight: double
                    +hearingLeft: int
                    +hearingRight: int
                    +systolicBp: int
                    +diastolicBp: int
                    +fastingGlucose: int
                    +totalCholesterol: int
                    +triglyceride: int
                    +hdlCholesterol: int
                    +ldlCholesterol: int
                    +hemoglobin: double
                    +urineProtein: int
                    +serumCreatinine: double
                    +ast: int
                    +alt: int
                    +gammaGtp: int
                    +smokingStatus: int
                    +drinkingStatus: int
                    +createdAt: LocalDateTime
                    +toDomain(): HealthCheckupRaw
                }
                
                class NormalRangeEntity {
                    +itemCode: String
                    +itemName: String
                    +genderCode: int
                    +normalMin: double
                    +normalMax: double
                    +cautionMin: double
                    +cautionMax: double
                    +dangerMin: double
                    +dangerMax: double
                    +unit: String
                    +description: String
                    +isActive: boolean
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +toDomain(): NormalRange
                }
                
                class HealthFileEntity {
                    +fileId: String
                    +userId: String
                    +fileName: String
                    +fileType: String
                    +fileUrl: String
                    +fileSize: long
                    +uploadStatus: String
                    +uploadedAt: LocalDateTime
                    +toDomain(): HealthFile
                }
            }
        }
        
        package "dto" {
            class HealthSyncResponse {
                +syncedRecords: int
                +newRecords: int
                +updatedRecords: int
                +skippedRecords: int
                +lastSyncedCheckup: Object
                +message: String
            }
            
            class HealthHistoryResponse {
                +checkupHistory: List<CheckupHistoryDto>
                +totalRecords: int
                +averageHealthScore: double
                +trendAnalysis: String
                +normalRangeReference: Object
            }
            
            class CheckupHistoryDto {
                +referenceYear: int
                +heightCm: double
                +weightKg: double
                +waistCm: double
                +bmi: double
                +systolicBp: int
                +diastolicBp: int
                +fastingGlucose: int
                +totalCholesterol: int
                +healthScore: int
                +riskLevel: String
                +abnormalIndicators: List<String>
                +analysisDate: String
            }
            
            class CheckupFileRequest {
                +userId: String
                +fileName: String
                +fileType: String
                +fileContent: String
            }
            
            class FileUploadResponse {
                +fileId: String
                +uploadUrl: String
                +status: String
                +message: String
            }
            
            class NormalRangeResponse {
                +normalRanges: List<NormalRangeDto>
                +genderCode: int
            }
            
            class NormalRangeDto {
                +itemCode: String
                +itemName: String
                +genderCode: int
                +normalMin: double
                +normalMax: double
                +cautionMin: double
                +cautionMax: double
                +dangerMin: double
                +dangerMax: double
                +unit: String
            }
        }
    }
}

' 관계 설정
AuthController --> AuthUseCase
AuthController --> UserUseCase
UserController --> UserUseCase
AuthUseCase --> AuthDomainService
AuthUseCase --> UserRepository
UserUseCase --> UserDomainService
UserUseCase --> UserRepository
UserUseCase --> OccupationRepository
AuthDomainService --> GoogleAuthAdapter
HealthController --> CheckupSyncUseCase
HealthController --> CheckupQueryUseCase
HealthController --> FileUploadUseCase
CheckupSyncUseCase --> HealthProfileDomainService
CheckupSyncUseCase --> CheckupAnalysisDomainService
CheckupSyncUseCase --> HealthRepository
CheckupSyncUseCase --> HealthCheckupRawRepository
CheckupSyncUseCase --> NormalRangeRepository
CheckupAnalysisDomainService --> NormalRangeDomainService

    package "goal-service" {
        class GoalServiceApplication {
            +main(args: String[]): void
        }
        
        package "interface-adapters" {
            package "controllers" {
                class GoalController {
                    -goalUseCase: GoalUseCase
                    +selectMissions(request: MissionSelectionRequest): ResponseEntity<GoalSetupResponse>
                    +getActiveMissions(userId: String): ResponseEntity<ActiveMissionsResponse>
                    +completeMission(missionId: String, request: MissionCompleteRequest): ResponseEntity<MissionCompleteResponse>
                    +getMissionHistory(userId: String, startDate: String, endDate: String, missionIds: String): ResponseEntity<MissionHistoryResponse>
                    +resetMissions(request: MissionResetRequest): ResponseEntity<MissionResetResponse>
                }
            }
            
            package "adapters" {
                class IntelligenceServiceAdapter {
                    -intelligenceServiceClient: IntelligenceServiceClient
                    +requestNewMissionRecommendations(userId: String, reason: String): List<MissionRecommendation>
                    +getMissionRecommendations(userId: String, preferences: List<String>): List<MissionRecommendation>
                }
                
                class UserServiceAdapter {
                    -userServiceClient: UserServiceClient
                    +getUserInfo(userId: String): UserInfo
                    +getUserOccupationInfo(userId: String): OccupationInfo
                }
                
                class CacheAdapter {
                    -redisTemplate: RedisTemplate
                    +getCachedActiveMissions(userId: String): ActiveMissionsResponse
                    +cacheActiveMissions(userId: String, response: ActiveMissionsResponse): void
                    +getCachedMissionHistory(userId: String, period: String): MissionHistoryResponse
                    +cacheMissionHistory(userId: String, period: String, response: MissionHistoryResponse): void
                    +invalidateUserCaches(userId: String): void
                    +invalidateActiveMissionsCache(userId: String): void
                }
                
                class EventPublisherAdapter {
                    -serviceBusTemplate: ServiceBusTemplate
                    +publishGoalSetEvent(userId: String, goalId: String, missions: List<Mission>): void
                    +publishMissionCompletedEvent(userId: String, missionId: String, achievementData: AchievementData): void
                    +publishGoalResetEvent(userId: String, reason: String, newRecommendations: List<MissionRecommendation>): void
                }
            }
        }
        
        package "application-services" {
            class GoalUseCase {
                -goalDomainService: GoalDomainService
                -missionProgressDomainService: MissionProgressDomainService
                -goalRepository: GoalRepository
                -missionProgressRepository: MissionProgressRepository
                -intelligenceServiceAdapter: IntelligenceServiceAdapter
                -cacheAdapter: CacheAdapter
                -eventPublisher: EventPublisherAdapter
                +selectMissions(request: MissionSelectionRequest): GoalSetupResponse
                +getActiveMissions(userId: String): ActiveMissionsResponse
                +completeMission(missionId: String, request: MissionCompleteRequest): MissionCompleteResponse
                +getMissionHistory(userId: String, startDate: String, endDate: String, missionIds: String): MissionHistoryResponse
                +resetMissions(request: MissionResetRequest): MissionResetResponse
            }
        }
        
        package "domain" {
            package "model" {
                class UserMissionGoal {
                    +goalId: String
                    +userId: String
                    +isActive: boolean
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +activateGoal(): void
                    +deactivateGoal(): void
                }
                
                class UserMission {
                    +id: Long
                    +goalId: String
                    +userId: String
                    +missionId: String
                    +missionTitle: String
                    +missionDescription: String
                    +category: String
                    +difficulty: String
                    +estimatedTimeMinutes: int
                    +isActive: boolean
                    +currentStreakDays: int
                    +totalCompletedCount: int
                    +startDate: LocalDate
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +updateStreakDays(newStreak: int): void
                    +incrementCompletedCount(): void
                    +resetStreak(): void
                }
                
                class MissionProgress {
                    +id: Long
                    +userId: String
                    +missionId: String
                    +completedAt: LocalDateTime
                    +notes: String
                    +earnedPoints: int
                    +consecutiveDays: int
                    +isValidProgress(): boolean
                    +calculateEarnedPoints(difficulty: String, streak: int): int
                }
                
                class ActiveMission {
                    +missionId: String
                    +title: String
                    +description: String
                    +status: String
                    +completedToday: boolean
                    +streakDays: int
                    +nextReminderTime: String
                    +category: String
                    +difficulty: String
                    +isCompletedToday(): boolean
                    +getProgressStatus(): String
                }
                
                class MissionStatistics {
                    +missionId: String
                    +title: String
                    +achievementRate: double
                    +completedDays: int
                    +totalDays: int
                    +bestStreak: int
                    +averageCompletionTime: String
                    +calculateAchievementRate(): double
                    +getBestStreakPeriod(): String
                }
                
                class AchievementData {
                    +missionId: String
                    +achievementType: String
                    +consecutiveDays: int
                    +totalAchievements: int
                    +earnedPoints: int
                    +achievedAt: LocalDateTime
                    +isSignificantAchievement(): boolean
                }
            }
            
            package "services" {
                class GoalDomainService {
                    +validateMissionSelection(userId: String, missionIds: List<String>): void
                    +checkMaximumMissions(missionIds: List<String>): void
                    +deactivateExistingGoal(goal: UserMissionGoal): UserMissionGoal
                    +createNewGoalWithMissions(userId: String, missionIds: List<String>): UserMissionGoal
                    +generateGoalId(): String
                    +validateMissionCompletion(userId: String, missionId: String): void
                }
                
                class MissionProgressDomainService {
                    +calculateMissionProgress(missions: List<UserMission>): List<ActiveMission>
                    +calculateCompletionRate(missions: List<UserMission>): double
                    +calculateStreakDays(missions: List<UserMission>): Map<String, Integer>
                    +determineTodayStatus(missions: List<UserMission>): Map<String, Boolean>
                    +recordMissionCompletion(userId: String, missionId: String, completionData: MissionCompleteRequest): MissionProgress
                    +calculateNewStreakDays(previousProgress: List<MissionProgress>): int
                    +calculateEarnedPoints(mission: UserMission, streakDays: int): int
                    +updateMissionStatistics(userId: String, missionId: String): void
                    +analyzeAchievementStatistics(historyData: List<MissionProgress>): MissionStatistics
                    +generateInsights(statistics: MissionStatistics): List<String>
                    +prepareChartData(histories: List<MissionProgress>): Object
                }
            }
            
            package "repositories" {
                interface GoalRepository {
                    +findActiveGoalByUserId(userId: String): Optional<UserMissionGoal>
                    +saveGoalWithMissions(goal: UserMissionGoal, missions: List<UserMission>): UserMissionGoal
                    +updateGoalStatus(goalId: String, isActive: boolean): void
                    +findActiveMissionsByUserId(userId: String): List<UserMission>
                    +findUserMission(userId: String, missionId: String): Optional<UserMission>
                    +updateMissionStats(missionId: String, stats: MissionStatistics): void
                }
                
                interface MissionProgressRepository {
                    +findTodayProgress(userId: String, missionId: String): Optional<MissionProgress>
                    +saveMissionProgress(progress: MissionProgress): MissionProgress
                    +findMissionHistoryByPeriod(userId: String, startDate: LocalDate, endDate: LocalDate, missionIds: List<String>): List<MissionProgress>
                    +findProgressByUserAndMission(userId: String, missionId: String): List<MissionProgress>
                    +calculateAchievementRates(userId: String, period: String): Map<String, Double>
                }
            }
        }
        
        package "infrastructure" {
            package "repositories" {
                class GoalRepositoryImpl {
                    -entityManager: EntityManager
                    +findActiveGoalByUserId(userId: String): Optional<UserMissionGoal>
                    +saveGoalWithMissions(goal: UserMissionGoal, missions: List<UserMission>): UserMissionGoal
                    +updateGoalStatus(goalId: String, isActive: boolean): void
                    +findActiveMissionsByUserId(userId: String): List<UserMission>
                    +findUserMission(userId: String, missionId: String): Optional<UserMission>
                    +updateMissionStats(missionId: String, stats: MissionStatistics): void
                }
                
                class MissionProgressRepositoryImpl {
                    -entityManager: EntityManager
                    +findTodayProgress(userId: String, missionId: String): Optional<MissionProgress>
                    +saveMissionProgress(progress: MissionProgress): MissionProgress
                    +findMissionHistoryByPeriod(userId: String, startDate: LocalDate, endDate: LocalDate, missionIds: List<String>): List<MissionProgress>
                    +findProgressByUserAndMission(userId: String, missionId: String): List<MissionProgress>
                    +calculateAchievementRates(userId: String, period: String): Map<String, Double>
                }
            }
            
            package "entities" {
                class UserMissionGoalEntity {
                    +goalId: String
                    +userId: String
                    +isActive: boolean
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +toDomain(): UserMissionGoal
                    +fromDomain(goal: UserMissionGoal): UserMissionGoalEntity
                }
                
                class UserMissionEntity {
                    +id: Long
                    +goalId: String
                    +userId: String
                    +missionId: String
                    +missionTitle: String
                    +missionDescription: String
                    +category: String
                    +difficulty: String
                    +estimatedTimeMinutes: int
                    +isActive: boolean
                    +currentStreakDays: int
                    +totalCompletedCount: int
                    +startDate: LocalDate
                    +createdAt: LocalDateTime
                    +updatedAt: LocalDateTime
                    +toDomain(): UserMission
                    +fromDomain(mission: UserMission): UserMissionEntity
                }
                
                class MissionProgressEntity {
                    +id: Long
                    +userId: String
                    +missionId: String
                    +completedAt: LocalDateTime
                    +notes: String
                    +earnedPoints: int
                    +consecutiveDays: int
                    +createdAt: LocalDateTime
                    +toDomain(): MissionProgress
                    +fromDomain(progress: MissionProgress): MissionProgressEntity
                }
            }
        }
        
        package "dto" {
            class MissionSelectionRequest {
                +userId: String
                +selectedMissionIds: List<String>
            }
            
            class GoalSetupResponse {
                +goalId: String
                +selectedMissions: List<SelectedMissionDto>
                +message: String
                +setupCompletedAt: String
            }
            
            class SelectedMissionDto {
                +missionId: String
                +title: String
                +description: String
                +startDate: String
            }
            
            class ActiveMissionsResponse {
                +dailyMissions: List<ActiveMissionDto>
                +totalMissions: int
                +todayCompletedCount: int
                +completionRate: double
            }
            
            class ActiveMissionDto {
                +missionId: String
                +title: String
                +description: String
                +status: String
                +completedToday: boolean
                +streakDays: int
                +nextReminderTime: String
            }
            
            class MissionCompleteRequest {
                +userId: String
                +completed: boolean
                +completedAt: String
                +notes: String
            }
            
            class MissionCompleteResponse {
                +message: String
                +status: String
                +achievementMessage: String
                +newStreakDays: int
                +totalCompletedCount: int
                +earnedPoints: int
            }
            
            class MissionHistoryResponse {
                +totalAchievementRate: double
                +periodAchievementRate: double
                +bestStreak: int
                +missionStats: List<MissionStatDto>
                +chartData: Object
                +period: PeriodDto
                +insights: List<String>
            }
            
            class MissionStatDto {
                +missionId: String
                +title: String
                +achievementRate: double
                +completedDays: int
                +totalDays: int
            }
            
            class PeriodDto {
                +startDate: String
                +endDate: String
            }
            
            class MissionResetRequest {
                +userId: String
                +reason: String
                +currentMissionIds: List<String>
            }
            
            class MissionResetResponse {
                +message: String
                +newRecommendations: List<MissionRecommendationDto>
                +resetCompletedAt: String
            }
            
            class MissionRecommendationDto {
                +missionId: String
                +title: String
                +description: String
                +category: String
            }
        }
    }
    
    package "intelligence-service" {
        class IntelligenceServiceApplication {
            +main(args: String[]): void
        }
        
        package "interface-adapters" {
            package "controllers" {
                class AnalysisController {
                    -healthAnalysisUseCase: HealthAnalysisUseCase
                    +generateHealthDiagnosis(userId: String): ResponseEntity<HealthDiagnosisResponse>
                    +recommendMissions(request: MissionRecommendationRequest): ResponseEntity<MissionRecommendationResponse>
                }
                
                class ChatController {
                    -chatUseCase: ChatUseCase
                    +processChat(request: ChatRequest): ResponseEntity<ChatResponse>
                    +getChatHistory(sessionId: String, messageLimit: int): ResponseEntity<ChatHistoryResponse>
                }
                
                class NotificationController {
                    -notificationUseCase: NotificationUseCase
                    +generateCelebrationMessage(request: CelebrationRequest): ResponseEntity<CelebrationResponse>
                    +generateEncouragementMessage(request: EncouragementRequest): ResponseEntity<EncouragementResponse>
                }
                
                class BatchController {
                    -batchUseCase: BatchUseCase
                    +processBatchNotifications(request: BatchNotificationRequest): ResponseEntity<BatchNotificationResponse>
                }
            }
            
            package "adapters" {
                class HealthServiceAdapter {
                    -healthServiceClient: HealthServiceClient
                    +getLatestHealthCheckup(userId: String): HealthCheckupData
                    +getHealthAnalysisData(userId: String): HealthAnalysisData
                    +getHealthTrendData(userId: String): HealthTrendData
                }
                
                class UserServiceAdapter {
                    -userServiceClient: UserServiceClient
                    +getUserProfile(userId: String): UserProfile
                    +getUserOccupationInfo(userId: String): OccupationInfo
                }
                
                class GoalServiceAdapter {
                    -goalServiceClient: GoalServiceClient
                    +getMissionDetails(missionId: String): MissionDetails
                    +getUserDailyProgress(userId: String): DailyProgress
                    +getAllUsersProgress(targetUsers: List<String>): Map<String, DailyProgress>
                }
                
                class ClaudeApiAdapter {
                    -claudeApiClient: ClaudeApiClient
                    -circuitBreaker: CircuitBreaker
                    +requestHealthDiagnosis(prompt: String): String
                    +requestMissionRecommendations(prompt: String): String
                    +requestChatResponse(prompt: String): String
                    +requestCelebrationMessage(prompt: String): String
                    +requestEncouragementMessage(prompt: String): String
                    +requestBatchNotification(prompt: String): String
                }
                
                class CacheAdapter {
                    -redisTemplate: RedisTemplate
                    +getCachedDiagnosis(userId: String): HealthDiagnosisResponse
                    +cacheDiagnosis(userId: String, response: HealthDiagnosisResponse): void
                    +getCachedChatHistory(sessionId: String): List<ChatMessage>
                    +cacheChatHistory(sessionId: String, history: List<ChatMessage>): void
                    +getCachedEncouragementMessage(userId: String, progressLevel: String): String
                    +cacheEncouragementMessage(userId: String, progressLevel: String, message: String): void
                    +invalidateUserCaches(userId: String): void
                }
                
                class EventPublisherAdapter {
                    -serviceBusTemplate: ServiceBusTemplate
                    +publishHealthAnalysisEvent(userId: String, analysisResult: AnalysisResult): void
                    +publishChatSessionEvent(sessionId: String, eventType: String): void
                    +publishBatchNotificationEvents(notifications: List<NotificationEvent>): void
                }
            }
        }
        
        package "application-services" {
            class HealthAnalysisUseCase {
                -aiAnalysisDomainService: AiAnalysisDomainService
                -healthServiceAdapter: HealthServiceAdapter
                -userServiceAdapter: UserServiceAdapter
                -claudeApiAdapter: ClaudeApiAdapter
                -cacheAdapter: CacheAdapter
                +generateHealthDiagnosis(userId: String): HealthDiagnosisResponse
                +recommendMissions(request: MissionRecommendationRequest): MissionRecommendationResponse
            }
            
            class ChatUseCase {
                -chatDomainService: ChatDomainService
                -chatHistoryRepository: ChatHistoryRepository
                -claudeApiAdapter: ClaudeApiAdapter
                -cacheAdapter: CacheAdapter
                +processChat(request: ChatRequest): ChatResponse
                +getChatHistory(sessionId: String, messageLimit: int): ChatHistoryResponse
            }
            
            class NotificationUseCase {
                -notificationDomainService: NotificationDomainService
                -goalServiceAdapter: GoalServiceAdapter
                -claudeApiAdapter: ClaudeApiAdapter
                -cacheAdapter: CacheAdapter
                +generateCelebrationMessage(request: CelebrationRequest): CelebrationResponse
                +generateEncouragementMessage(request: EncouragementRequest): EncouragementResponse
            }
            
            class BatchUseCase {
                -notificationDomainService: NotificationDomainService
                -goalServiceAdapter: GoalServiceAdapter
                -claudeApiAdapter: ClaudeApiAdapter
                -eventPublisher: EventPublisherAdapter
                +processBatchNotifications(request: BatchNotificationRequest): BatchNotificationResponse
            }
        }
        
        package "domain" {
            package "model" {
                class AiDiagnosis {
                    +userId: String
                    +healthScore: int
                    +riskLevel: String
                    +threeSentenceSummary: List<String>
                    +occupationConsiderations: String
                    +analysisTimestamp: LocalDateTime
                    +confidenceScore: double
                    +isHighRisk(): boolean
                    +requiresImmediateAttention(): boolean
                }
                
                class ChatSession {
                    +sessionId: String
                    +userId: String
                    +status: SessionStatus
                    +createdAt: LocalDateTime
                    +lastActivityAt: LocalDateTime
                    +messageCount: int
                    +context: String
                    +isActive(): boolean
                    +updateLastActivity(): void
                    +incrementMessageCount(): void
                }
                
                class ChatMessage {
                    +messageId: String
                    +sessionId: String
                    +role: MessageRole
                    +content: String
                    +timestamp: LocalDateTime
                    +messageOrder: int
                    +isUserMessage(): boolean
                    +isAssistantMessage(): boolean
                    +maskSensitiveInfo(): ChatMessage
                }
                
                class Mission {
                    +missionId: String
                    +title: String
                    +description: String
                    +category: MissionCategory
                    +difficulty: DifficultyLevel
                    +healthBenefit: String
                    +occupationRelevance: String
                    +estimatedTimeMinutes: int
                    +isApplicableForOccupation(occupation: String): boolean
                    +calculateDifficultyScore(): int
                }
                
                class AnalysisResult {
                    +userId: String
                    +analysisType: String
                    +result: String
                    +confidence: double
                    +createdAt: LocalDateTime
                    +metadata: Map<String, Object>
                    +isHighConfidence(): boolean
                    +getFormattedResult(): String
                }
                
                enum SessionStatus {
                    ACTIVE, INACTIVE, EXPIRED, TERMINATED
                }
                
                enum MessageRole {
                    USER, ASSISTANT, SYSTEM
                }
                
                enum MissionCategory {
                    EXERCISE, NUTRITION, STRESS_MANAGEMENT, SLEEP, PREVENTIVE_CARE
                }
                
                enum DifficultyLevel {
                    EASY, MEDIUM, HARD
                }
            }
            
            package "services" {
                class AiAnalysisDomainService {
                    +createDiagnosisPrompt(healthData: HealthCheckupData, userProfile: UserProfile): String
                    +formatHealthDataForAI(checkupData: HealthCheckupData): String
                    +parseAndValidateAIResponse(aiResponse: String): AiDiagnosis
                    +calculateConfidenceScore(healthData: HealthCheckupData, aiResponse: String): double
                    +generateMissionRecommendations(healthData: HealthAnalysisData, occupation: String, preferences: List<String>): List<Mission>
                    +createPersonalizedPrompt(data: MissionRecommendationRequest): String
                    +parseMissionRecommendations(aiResponse: String): List<Mission>
                    +validateAndEnrichMissions(missions: List<Mission>): List<Mission>
                }
                
                class ChatDomainService {
                    +validateChatSession(sessionId: String): ChatSession
                    +createNewChatSession(userId: String): ChatSession
                    +buildContextualPrompt(userMessage: String, chatHistory: List<ChatMessage>, context: String): String
                    +formatChatContext(history: List<ChatMessage>): String
                    +saveChatExchange(sessionId: String, userMessage: String, aiResponse: String): void
                    +formatChatHistory(rawHistory: List<ChatMessage>): List<ChatMessage>
                    +maskSensitiveInfo(messages: List<ChatMessage>): List<ChatMessage>
                }
                
                class NotificationDomainService {
                    +createCelebrationMessage(celebrationData: CelebrationRequest): String
                    +prepareCelebrationPrompt(data: CelebrationRequest): String
                    +enhanceCelebrationMessage(aiMessage: String, achievementData: AchievementData): CelebrationResponse
                    +analyzeProgressPattern(userId: String, missionsStatus: List<MissionStatus>, dailyProgress: DailyProgress): ProgressAnalysis
                    +calculateProgressLevel(data: ProgressAnalysis): String
                    +identifyFailurePoints(missionsStatus: List<MissionStatus>): List<String>
                    +createEncouragementPrompt(progressAnalysis: ProgressAnalysis): String
                    +generatePersonalizedNotification(user: UserInfo, progress: DailyProgress): String
                }
            }
            
            package "repositories" {
                interface ChatHistoryRepository {
                    +findChatSession(sessionId: String): Optional<ChatSession>
                    +saveChatSession(session: ChatSession): ChatSession
                    +getChatHistory(sessionId: String, limit: int): List<ChatMessage>
                    +saveChatMessages(sessionId: String, messages: List<ChatMessage>): void
                    +findChatHistoryBySession(sessionId: String, messageLimit: int): List<ChatMessage>
                    +updateSessionActivity(sessionId: String): void
                }
                
                interface AnalysisRepository {
                    +saveAnalysisResult(result: AnalysisResult): AnalysisResult
                    +findAnalysisHistoryByUser(userId: String): List<AnalysisResult>
                    +findLatestAnalysis(userId: String, analysisType: String): Optional<AnalysisResult>
                    +deleteOldAnalysisResults(beforeDate: LocalDateTime): void
                }
            }
        }
        
        package "infrastructure" {
            package "repositories" {
                class ChatHistoryRepositoryImpl {
                    -entityManager: EntityManager
                    +findChatSession(sessionId: String): Optional<ChatSession>
                    +saveChatSession(session: ChatSession): ChatSession
                    +getChatHistory(sessionId: String, limit: int): List<ChatMessage>
                    +saveChatMessages(sessionId: String, messages: List<ChatMessage>): void
                    +findChatHistoryBySession(sessionId: String, messageLimit: int): List<ChatMessage>
                    +updateSessionActivity(sessionId: String): void
                }
                
                class AnalysisRepositoryImpl {
                    -entityManager: EntityManager
                    +saveAnalysisResult(result: AnalysisResult): AnalysisResult
                    +findAnalysisHistoryByUser(userId: String): List<AnalysisResult>
                    +findLatestAnalysis(userId: String, analysisType: String): Optional<AnalysisResult>
                    +deleteOldAnalysisResults(beforeDate: LocalDateTime): void
                }
            }
            
            package "entities" {
                class ChatSessionEntity {
                    +sessionId: String
                    +userId: String
                    +status: String
                    +createdAt: LocalDateTime
                    +lastActivityAt: LocalDateTime
                    +messageCount: int
                    +context: String
                    +toDomain(): ChatSession
                    +fromDomain(session: ChatSession): ChatSessionEntity
                }
                
                class ChatMessageEntity {
                    +messageId: String
                    +sessionId: String
                    +role: String
                    +content: String
                    +timestamp: LocalDateTime
                    +messageOrder: int
                    +toDomain(): ChatMessage
                    +fromDomain(message: ChatMessage): ChatMessageEntity
                }
                
                class AnalysisResultEntity {
                    +id: Long
                    +userId: String
                    +analysisType: String
                    +result: String
                    +confidence: double
                    +createdAt: LocalDateTime
                    +metadata: String
                    +toDomain(): AnalysisResult
                    +fromDomain(result: AnalysisResult): AnalysisResultEntity
                }
            }
        }
        
        package "dto" {
            class HealthDiagnosisResponse {
                +threeSentenceSummary: List<String>
                +healthScore: int
                +riskLevel: String
                +occupationConsiderations: String
                +analysisTimestamp: String
                +confidenceScore: double
            }
            
            class MissionRecommendationRequest {
                +userId: String
                +currentHealthStatus: String
                +preferences: List<String>
            }
            
            class MissionRecommendationResponse {
                +missions: List<MissionDto>
                +recommendationReason: String
                +totalRecommended: int
            }
            
            class MissionDto {
                +missionId: String
                +title: String
                +description: String
                +category: String
                +difficulty: String
                +healthBenefit: String
                +occupationRelevance: String
                +estimatedTimeMinutes: int
            }
            
            class ChatRequest {
                +message: String
                +sessionId: String
                +context: String
            }
            
            class ChatResponse {
                +response: String
                +sessionId: String
                +timestamp: String
                +suggestedQuestions: List<String>
                +responseType: String
            }
            
            class ChatHistoryResponse {
                +sessionId: String
                +messages: List<ChatMessageDto>
                +totalMessageCount: int
                +cacheExpiration: String
            }
            
            class ChatMessageDto {
                +role: String
                +content: String
                +timestamp: String
            }
            
            class CelebrationRequest {
                +userId: String
                +missionId: String
                +achievementType: String
                +consecutiveDays: int
                +totalAchievements: int
            }
            
            class CelebrationResponse {
                +congratsMessage: String
                +achievementBadge: String
                +healthBenefit: String
                +nextMilestone: String
                +encouragementLevel: String
                +visualEffect: String
            }
            
            class EncouragementRequest {
                +userId: String
                +missionsStatus: List<MissionStatusDto>
            }
            
            class MissionStatusDto {
                +missionId: String
                +completed: boolean
            }
            
            class EncouragementResponse {
                +message: String
                +motivationType: String
                +timing: String
                +personalizedTip: String
                +priority: String
            }
            
            class BatchNotificationRequest {
                +triggerTime: String
                +targetUsers: List<String>
                +notificationType: String
            }
            
            class BatchNotificationResponse {
                +processedCount: int
                +successCount: int
                +failedCount: int
                +nextScheduledTime: String
            }
        }
    }
}